﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using HYView;

namespace YArchitech.Revit.MEP.Opening
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	public class CmdTopBottomDim : YJKCommandManual
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		protected override Result YJKExcute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			if (Convert.ToDouble(cmdData.Application.Application.VersionNumber) <= 2014.0)
			{
				MessageBox.Show("请在REVIT2015或更高版本运行此命令。");
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			CmdViewType types = CmdViewType.Elevation;
			if (SwitchView.SetUsableView(types, cmdData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			if (CmdTopBottomDim._hWndRevit == null)
			{
				CmdTopBottomDim._hWndRevit = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			this.m_doc = cmdData.Application.ActiveUIDocument.Document;
			DlgTopBottomDim instance = DlgTopBottomDim.GetInstance(cmdData);
			instance.Show(CmdTopBottomDim._hWndRevit);
			int wMsg = 7;
			CmdTopBottomDim.SendMessage(CmdTopBottomDim._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			Transaction transaction = new Transaction(this.m_doc, "墙洞标高");
			try
			{
				bool flag = true;
				for (;;)
				{
					transaction.Start();
					if (1 == instance.SelectMode)
					{
						flag = this.CreateSingle(instance);
					}
					else if (2 == instance.SelectMode)
					{
						flag = this.CreateRect(instance);
					}
					transaction.Commit();
					if (!flag)
					{
						if (!instance.ClickModeBtn)
						{
							break;
						}
						instance.ClickModeBtn = false;
					}
				}
			}
			catch (Exception)
			{
				transaction.RollBack();
				instance.Close();
				return Autodesk.Revit.UI.Result.Succeeded;
			}
			instance.Close();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		public bool CreateSingle(DlgTopBottomDim dlg)
		{
			try
			{
				Autodesk.Revit.DB.View activeView = this.m_doc.ActiveView;
				OpeningFilter openingFilter = new OpeningFilter();
				Element element = this.m_doc.GetElement(this.m_uiApp.ActiveUIDocument.Selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, openingFilter, "请选择需要标记的洞口"));
				if (dlg.TopDim)
				{
					Reference reference = this.FindTopMostReference(element);
					XYZ globalPoint = reference.GlobalPoint;
					try
					{
						this.m_doc.Create.NewSpotElevation(activeView, reference, globalPoint, globalPoint, globalPoint, globalPoint, true).DimensionType = dlg.SpotDimensionType;
					}
					catch
					{
					}
				}
				if (dlg.BottomDim)
				{
					Reference reference2 = this.FindBottomMostReference(element);
					XYZ globalPoint2 = reference2.GlobalPoint;
					try
					{
						this.m_doc.Create.NewSpotElevation(activeView, reference2, globalPoint2, globalPoint2, globalPoint2, globalPoint2, true).DimensionType = dlg.SpotDimensionType;
					}
					catch
					{
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		public bool CreateRect(DlgTopBottomDim dlg)
		{
			try
			{
				Autodesk.Revit.DB.View activeView = this.m_doc.ActiveView;
				OpeningFilter openingFilter = new OpeningFilter();
				foreach (Reference reference in this.m_uiDoc.Selection.PickObjects((Autodesk.Revit.UI.Selection.ObjectType)1, openingFilter, "请选择需要标记的洞口"))
				{
					Element element = this.m_doc.GetElement(reference);
					if (dlg.TopDim)
					{
						Reference reference2 = this.FindTopMostReference(element);
						XYZ globalPoint = reference2.GlobalPoint;
						try
						{
							this.m_doc.Create.NewSpotElevation(activeView, reference2, globalPoint, globalPoint, globalPoint, globalPoint, true).DimensionType = dlg.SpotDimensionType;
						}
						catch
						{
							continue;
						}
					}
					if (dlg.BottomDim)
					{
						Reference reference3 = this.FindBottomMostReference(element);
						XYZ globalPoint2 = reference3.GlobalPoint;
						try
						{
							this.m_doc.Create.NewSpotElevation(activeView, reference3, globalPoint2, globalPoint2, globalPoint2, globalPoint2, true).DimensionType = dlg.SpotDimensionType;
						}
						catch
						{
						}
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private Reference FindTopMostReference(Element e)
		{
			Document document = e.Document;
			SubTransaction subTransaction = new SubTransaction(document);
			try
			{
				subTransaction.Start();
				XYZ pDirection = new XYZ(0.0, 0.0, -1.0);
				View3D view3D = null;
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
				filteredElementCollector.OfClass(typeof(View3D));
				foreach (Element element in filteredElementCollector)
				{
					View3D view3D2 = (View3D)element;
					if (view3D2.Name == "盈建科三维模型浏览")
					{
						view3D = view3D2;
						break;
					}
				}
				if (view3D == null)
				{
                    ViewFamilyType viewFamilyType = new FilteredElementCollector(document).OfClass(typeof(ViewFamilyType)).Cast<ViewFamilyType>().FirstOrDefault((ViewFamilyType x) => 102 == (int)x.ViewFamily);
					view3D = View3D.CreateIsometric(document, viewFamilyType.Id);
					view3D.Name = "盈建科三维模型浏览";
				}
				BoundingBoxXYZ boundingBoxXYZ = e.get_BoundingBox(document.ActiveView);
				XYZ max = boundingBoxXYZ.Max;
				XYZ xyz = boundingBoxXYZ.Min;
				xyz = new XYZ(xyz.X, xyz.Y, max.Z);
				XYZ xyz2 = xyz.Add(max).Divide(2.0);
				xyz2 = new XYZ(xyz2.X, xyz2.Y, xyz2.Z + 0.2);
				IEnumerable<ReferenceWithContext> enumerable = RevitVersionFuncs.FindReferencesWithContextByDirection(document, xyz2, pDirection, view3D);
				double num = double.PositiveInfinity;
				Reference result = null;
				foreach (ReferenceWithContext referenceWithContext in enumerable)
				{
					int integerValue = referenceWithContext.GetReference().ElementId.IntegerValue;
					if (referenceWithContext.Proximity < num)
					{
						result = referenceWithContext.GetReference();
						num = referenceWithContext.Proximity;
					}
				}
				subTransaction.RollBack();
				return result;
			}
			catch (Exception)
			{
				subTransaction.RollBack();
			}
			return null;
		}

		private Reference FindBottomMostReference(Element e)
		{
			Document document = e.Document;
			SubTransaction subTransaction = new SubTransaction(document);
			subTransaction.Start();
			XYZ pDirection = new XYZ(0.0, 0.0, 1.0);
            ViewFamilyType viewFamilyType = new FilteredElementCollector(document).OfClass(typeof(ViewFamilyType)).Cast<ViewFamilyType>().FirstOrDefault((ViewFamilyType x) => 102 == (int)x.ViewFamily);
			View3D view3D = View3D.CreateIsometric(document, viewFamilyType.Id);
			view3D.Name = "盈建科三维模型浏览";
			BoundingBoxXYZ boundingBoxXYZ = e.get_BoundingBox(document.ActiveView);
			XYZ min = boundingBoxXYZ.Min;
			XYZ xyz = boundingBoxXYZ.Max;
			xyz = new XYZ(xyz.X, xyz.Y, min.Z);
			XYZ xyz2 = xyz.Add(min).Divide(2.0);
			xyz2 = new XYZ(xyz2.X, xyz2.Y, xyz2.Z - 0.2);
			IEnumerable<ReferenceWithContext> enumerable = RevitVersionFuncs.FindReferencesWithContextByDirection(document, xyz2, pDirection, view3D);
			double num = double.PositiveInfinity;
			Reference result = null;
			foreach (ReferenceWithContext referenceWithContext in enumerable)
			{
				Reference reference = referenceWithContext.GetReference();
				if (referenceWithContext.Proximity < num)
				{
					result = reference;
					num = referenceWithContext.Proximity;
				}
			}
			subTransaction.RollBack();
			return result;
		}

		protected new Autodesk.Revit.DB.Document m_doc;

		public static WindowHandle _hWndRevit;
	}
}
